
/*
 * Copyright 2002-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 *版权所有2002-2016原作者。
 *
 *根据Apache许可证2.0版许可（“许可证”）；
 *除非符合许可证的规定，否则您不得使用此文件。
 *您可以在以下网址获取许可证副本：
 *
 *https://www.apache.org/licenses/LICENSE-2.0
 *
 *除非适用法律要求或书面同意，软件
 *根据许可证进行的分发是在“按原样”的基础上进行的，
 *无任何明示或暗示的保证或条件。
 *有关管理权限的特定语言，请参阅许可证和
 *许可证下的限制。
 */

package org.springframework.jndi;

import javax.naming.NamingException;

import org.springframework.core.env.PropertySource;
import org.springframework.lang.Nullable;

/**
 * {@link PropertySource} implementation that reads properties from an underlying Spring
 * {@link JndiLocatorDelegate}.
 *
 * <p>By default, the underlying {@code JndiLocatorDelegate} will be configured with its
 * {@link JndiLocatorDelegate#setResourceRef(boolean) "resourceRef"} property set to
 * {@code true}, meaning that names looked up will automatically be prefixed with
 * "java:comp/env/" in alignment with published
 * <a href="https://download.oracle.com/javase/jndi/tutorial/beyond/misc/policy.html">JNDI
 * naming conventions</a>. To override this setting or to change the prefix, manually
 * configure a {@code JndiLocatorDelegate} and provide it to one of the constructors here
 * that accepts it. The same applies when providing custom JNDI properties. These should
 * be specified using {@link JndiLocatorDelegate#setJndiEnvironment(java.util.Properties)}
 * prior to construction of the {@code JndiPropertySource}.
 *
 * <p>Note that {@link org.springframework.web.context.support.StandardServletEnvironment
 * StandardServletEnvironment} includes a {@code JndiPropertySource} by default, and any
 * customization of the underlying {@link JndiLocatorDelegate} may be performed within an
 * {@link org.springframework.context.ApplicationContextInitializer
 * ApplicationContextInitializer} or {@link org.springframework.web.WebApplicationInitializer
 * WebApplicationInitializer}.
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 * @see JndiLocatorDelegate
 * @see org.springframework.context.ApplicationContextInitializer
 * @see org.springframework.web.WebApplicationInitializer
 * @see org.springframework.web.context.support.StandardServletEnvironment
 */
/**
 *｛@link PropertySource｝实现，该实现从底层Spring读取属性
 *｛@link JndiLocatorDelegate｝。
 *
 *<p>默认情况下，底层｛@code JndiLocatorDelegate｝将使用其
 *｛@link JndiLocatorDelegate#setResourceRef（布尔值）“resourceRef”｝属性设置为
 *｛@code true｝，这意味着查找到的名称将自动以
 *“java:comp/env/”与已发布的一致
 *<a href=“https://download.oracle.com/javase/jndi/tutorial/beyond/misc/policy.html“>JNDI
 *命名约定</a>。要覆盖此设置或更改前缀，请手动
 *配置｛@code JndiLocatorDelegate｝并将其提供给此处的一个构造函数
 *接受它。这同样适用于提供自定义JNDI属性。这些应该
 *使用｛@link JndiLocatorDelegate#setJndiEnvironment（java.util.Properties）｝指定
 *在构造｛@code JndiPropertySource｝之前。
 *
 *<p>请注意，｛@link org.springframework.web.context.support.StandardServlet环境
 *StandardServletEnvironment｝默认情况下包括｛@code JndiPropertySource｝，并且
 *可以在
 *｛@link org.springframework.context.ApplicationContextInitializer
 *ApplicationContextInitializer｝或｛@link org.springframework.web.WebApplicationInitializer
 *WebApplicationInitializer｝。
 *
 *@作者Chris Beams
 *@作者于尔根·霍勒
 *@自3.1起
 *@参见JndiLocatorDelegate
 *@参见org.springframework.context.ApplicationContextInitializer
 *@参见org.springframework.web.WebApplicationInitializer
 *@参见org.springframework.web.context.support.StandardServlet环境
 */
public class JndiPropertySource extends PropertySource<JndiLocatorDelegate> {

	/**
	 * Create a new {@code JndiPropertySource} with the given name
	 * and a {@link JndiLocatorDelegate} configured to prefix any names with
	 * "java:comp/env/".
	 */
	/**
	 *使用给定的名称创建新的｛@code JndiPropertySource｝
	 *和配置为在任何名称前面加上
	 *“java:comp/env/”。
	 */
	public JndiPropertySource(String name) {
		this(name, JndiLocatorDelegate.createDefaultResourceRefLocator());
	}

	/**
	 * Create a new {@code JndiPropertySource} with the given name and the given
	 * {@code JndiLocatorDelegate}.
	 */
	/**
	 *使用给定的名称和
	 *｛@code JndiLocatorDelegate｝。
	 */
	public JndiPropertySource(String name, JndiLocatorDelegate jndiLocator) {
		super(name, jndiLocator);
	}


	/**
	 * This implementation looks up and returns the value associated with the given
	 * name from the underlying {@link JndiLocatorDelegate}. If a {@link NamingException}
	 * is thrown during the call to {@link JndiLocatorDelegate#lookup(String)}, returns
	 * {@code null} and issues a DEBUG-level log statement with the exception message.
	 */
	/**
	 *此实现查找并返回与给定
	 *来自基础｛@link JndiLocatorDelegate｝的名称。如果出现｛@link NamingException｝
	 *在调用｛@link JndiLocatorDelegate#lookup（String）｝期间抛出，返回
	 *｛@code null｝，并发出带有异常消息的DEBUG级别日志语句。
	 */
	@Override
	@Nullable
	public Object getProperty(String name) {
		if (getSource().isResourceRef() && name.indexOf(':') != -1) {
			// We're in resource-ref (prefixing with "java:comp/env") mode. Let's not bother
			// 我们处于resource-ref（前缀为“java:comp/env”）模式。我们别麻烦了
			// with property names with a colon it since they're probably just containing a
			// 带有冒号的属性名称，因为它们可能只包含
			// default value clause, very unlikely to match including the colon part even in
			// default value子句，即使在
			// a textual property source, and effectively never meant to match that way in
			// 文本属性源，并且实际上从未打算以这种方式匹配
			// JNDI where a colon indicates a separator between JNDI scheme and actual name.
			// JNDI，其中冒号表示JNDI方案和实际名称之间的分隔符。
			return null;
		}

		try {
			Object value = this.source.lookup(name);
			if (logger.isDebugEnabled()) {
				logger.debug("JNDI lookup for name [" + name + "] returned: [" + value + "]");
			}
			return value;
		}
		catch (NamingException ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("JNDI lookup for name [" + name + "] threw NamingException " +
						"with message: " + ex.getMessage() + ". Returning null.");
			}
			return null;
		}
	}

}
